package com.ssttevee.taskmanagerapp;

import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramSocket;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;

import com.ssttevee.taskmanagerapp.R;
import com.ssttevee.taskmanagerapp.adapter.PlayersListAdapter;
import com.ssttevee.taskmanagerapp.adapter.ServerInfoAdapter;
import com.ssttevee.taskmanagerapp.tasks.ServerQuery;
import com.ssttevee.taskmanagerapp.tasks.Task;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;

public class ViewInfoActivity extends Activity {
	
	private TaskManagerApplication app;
	private long id;
	private String name;
	private String host;
	private String motd;
	private int max_players;
	private int online_players;
	private String players;
	private int latency;
	private int gs4_port;
	private String version;
	private int times_online;
	private int times_checked;
	private boolean online;
	private ArrayList<String[]> data = new ArrayList<String[]>();
	private ArrayList<Bitmap> bmArray = new ArrayList<Bitmap>();
	private ListView lv;
	private ServerInfoAdapter adapter;
	private double uptime;
	private ServerQuery sq = new ServerQuery();
	private int repollfreq = 120; // in Seconds
	private AlertDialog deleteConfirmDialog;
	private ProgressBar loadSpinner;
	private AlertDialog deleteServerDialog;
	private Task t;
	private ProgressDialog progdialog;
	private boolean cancelTask = false;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.view_info);
		
		viewSetup();
	}
	
	@Override
	public void onResume() {
		app = (TaskManagerApplication) getApplication();
		t = app.getTaskById((int) id);

		name = t.getName();
		host = t.getHost();
		motd = t.getMotd();
		max_players = t.getMaxPlayers();
		online_players = t.getOnlinePlayers();
		players = t.getPlayers();
		latency = t.getLatency();
		gs4_port = t.getGs4Port();
		version = t.getVersion();
		times_online = t.getTimesOnline();
		times_checked = t.getTimesChecked();
		online = t.isOnline();
		uptime = (double) times_online / (double) times_checked;
		
		((TextView)findViewById(R.id.header_title)).setText(name);
		Task t = new Task(id, name, host, motd, max_players, online_players, players, (online ? latency : -1), version, times_online, times_checked, online);
		t.setGs4Port(gs4_port);
		changeData(t);
		super.onResume();
	}
	
	@Override
	public void onPause() {
		super.onPause();
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	private void viewSetup() {
		TextView headerTitle = (TextView)findViewById(R.id.header_title);
		Bundle extras = getIntent().getExtras(); 
		loadSpinner = (ProgressBar)findViewById(R.id.at_spinner);
		loadSpinner.setVisibility(View.INVISIBLE);
		
		if(extras != null) {
			id = extras.getLong("id");
		}
		
		app = (TaskManagerApplication) getApplication();
		t = app.getTaskById((int) id);

		name = t.getName();
		host = t.getHost();
		motd = t.getMotd();
		max_players = t.getMaxPlayers();
		online_players = t.getOnlinePlayers();
		players = t.getPlayers();
		latency = t.getLatency();
		gs4_port = t.getGs4Port();
		version = t.getVersion();
		times_online = t.getTimesOnline();
		times_checked = t.getTimesChecked();
		online = t.isOnline();
		uptime = (double) times_online / (double) times_checked;
		
		headerTitle.setText(name);
		
		// data.add(new String[] {"Server Name", name});
		data.add(new String[] {"Game Address", host});
		data.add(new String[] {"Motd", motd});
		data.add(new String[] {"Slots", online_players + "/" + max_players});
		data.add(new String[] {"Players List", players});
		data.add(new String[] {"Ping", latency + "ms"});
		data.add(new String[] {"Uptime", uptime + "%"});
		data.add(new String[] {"Status", (online ? "Online" : "Offline")});
		data.add(new String[] {"Version", version});

		if(this.gs4_port > 0) {
		} else {
			data.remove(7);
			data.remove(3);
		}
		
		lv = (ListView)findViewById(R.id.server_data);
		adapter = new ServerInfoAdapter(data, this);
		lv.setAdapter(adapter);
		
		lv.setOnItemClickListener( new OnItemClickListener() {

			public void onItemClick(AdapterView<?> arg0, View v, int pos, long id) {
				// View current = adapter.getView(pos, null, null);
				if(pos == 3 && ViewInfoActivity.this.gs4_port > 0){
					SudoMethod sm = new SudoMethod("loadFaces");
					sm.execute(ViewInfoActivity.this.players.split(", "));
				}
			}
		});
	}

	protected void delete() {
		deleteServerDialog = new AlertDialog.Builder(this)
			.setTitle("Confirm Delete")
			.setMessage("Are you sure you want to delete this?  All data collected from this server will be lost.")
			.setNeutralButton("I'm Sure!", new AlertDialog.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					app = (TaskManagerApplication) getApplication();
					app.delTasks(id);
					Toast.makeText(getBaseContext(), name + " deleted", Toast.LENGTH_SHORT).show();
					finish();
				}
			})
			.setNegativeButton("No", new AlertDialog.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					deleteServerDialog.cancel();
				}
			}).create();
		deleteServerDialog.show();
	}

	public void repollButtonClickHandler(View target) {
		if(isInternetAvavilable()) {
			SudoMethod sm = new SudoMethod("repoll");
			if(!(gs4_port > 0)) {
				sm.execute("poll", host);
			} else {
				sm.execute("both", host, gs4_port + "");
			}
		} else {
			Toast.makeText(getBaseContext(), "Network Unavailable", Toast.LENGTH_SHORT).show();
		}
	}
	
	public void importButtonClickHandler(View target) {
		Toast.makeText(getBaseContext(), "Importing not available yet", Toast.LENGTH_SHORT).show();
	}
	   
	@Override
	protected Dialog onCreateDialog(int id) {
	 // TODO Auto-generated method stub
	 Dialog dialog = null;
		ListView dlv;
		switch(id) {
		case 0:
			
			dialog = new Dialog(ViewInfoActivity.this);
			dialog.setContentView(R.layout.players_list_dialog);
			dialog.setTitle("Current Online Players");
			Button closeBtn = (Button)dialog.findViewById(R.id.close_diag_btn);
			
			
			dlv = (ListView)dialog.findViewById(R.id.plist_diaglv);
			PlayersListAdapter adapter = new PlayersListAdapter(this.players.split(", "), this, bmArray);
			dlv.setAdapter(adapter);
			closeBtn.setOnClickListener( new View.OnClickListener() {
				public void onClick(View v) {
					dismissDialog(0);
				}
			});
			break;
		case 1:
			deleteConfirmDialog = new AlertDialog.Builder(this)
			.setTitle(R.string.unsaved_changed_title)
			.setMessage("Do you really want to lose this data?")
			.setNeutralButton(R.string.discard, new AlertDialog.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					finish();
				}
			})
			.setNegativeButton(R.string.cancel, new AlertDialog.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					ViewInfoActivity.this.deleteConfirmDialog.cancel();
				}
			}).create();
		}
		return dialog;
	}  

	public void csUpdateUI() {
		Task t = new Task(id, name, host, sq.getMotd(), sq.getMaxPlayers(), sq.getPlayerCount(), sq.getPlayers(), (online ? sq.getLatency() : -1), sq.getVersion(), times_online, times_checked, online);
		t.setGs4Port(gs4_port);
		app = (TaskManagerApplication) getApplication();
		app.saveTask(t);
		changeData(t);
	}
	
	protected void changeData(Task t) {
		ArrayList<String> etc = new ArrayList<String>();
		// etc.add(t.getName());
		etc.add(t.getHost());
		etc.add(t.getMotd());
		etc.add(t.getOnlinePlayers() + "/" + t.getMaxPlayers());
		if(gs4_port > 0) {
			etc.add(t.getPlayers());
		}
		etc.add((t.isOnline() ? t.getLatency() + " ms" : "-1 ms"));
		double uptime = (double) t.getTimesOnline() / (double) t.getTimesChecked();
		uptime = uptime * 10000;
		uptime = Math.floor(uptime);
		uptime = uptime / 100;
		etc.add(uptime + "%");
		// etc.add(t.getTimesOnline() + "/" + t.getTimesChecked());
		etc.add((t.isOnline() ? "Online" : "Offline"));
		if(gs4_port > 0) {
			etc.add(t.getVersion());
		}
		
		adapter.changeValue(etc);
		adapter.forceReload();
	}

	public void showSpinner() {
		loadSpinner.setVisibility(View.VISIBLE);
	}
	
	public void hideSpinner() {
		loadSpinner.setVisibility(View.INVISIBLE);
	}
	
	public boolean isInternetAvavilable() {
		ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
		return activeNetworkInfo != null;
	}

	private class SudoMethod extends AsyncTask<String, String, String> {
		private String[] messages = new String[]{"Connection Refused", "Connection Successful", "Unable to find host", "Query Attempt Failed", "Query Request Successful"};
		private int rmsg;
		private URL url;
		private Bitmap bitmap;
		private String method;

		public SudoMethod(String str) {
			this.method = str;
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			if(this.method == "loadFaces") {
				progdialog = ProgressDialog.show(ViewInfoActivity.this, "", "Loading Faces...", true);
				progdialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
			        public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
			            if (keyCode == KeyEvent.KEYCODE_BACK && progdialog.isShowing()) {
			    			cancelTask = true;
			    			progdialog.dismiss();
			                return true;
			            }
			            return false;
			        }
			    });
			} else if(this.method == "repoll") {
				((TextView)findViewById(R.id.repoll_btn)).setEnabled(false);
				showSpinner();
			} else if(this.method == "timer") {
				String waittime = "";
				int days = (int) Math.floor((repollfreq)/86400);
				int hrs = (int) Math.floor((repollfreq - (days*86400))/3600);
				int mins = (int) Math.floor((repollfreq - (hrs*3600))/60);
				int secs = (repollfreq - (mins*60) - (hrs*3600) - (days*86400));
				if(days > 0) waittime = waittime + days + "days ";
				if(hrs > 0) waittime = waittime + mins + "hrs ";
				if(mins > 0) waittime = waittime + mins + "min ";
				waittime = waittime + secs + "s";
				((TextView) findViewById(R.id.repoll_btn)).setText("Wait " + waittime);
				((TextView) findViewById(R.id.repoll_btn)).setEnabled(false);
				
			}
		}
		
		@Override
		protected String doInBackground(String... params) {
			if(this.method == "loadFaces") {
				for(String name : params) {
					if(cancelTask == false) {
						try {
							url = new URL("http://minotar.net/avatar/" + name + "/100.png");
							HttpURLConnection connection = (HttpURLConnection) url.openConnection();
							connection.setDoInput(true);
							connection.connect();
							InputStream input = connection.getInputStream();
							bitmap = getRoundedCornerBitmap(BitmapFactory.decodeStream(input), 7);
						} catch (MalformedURLException e) {
							bitmap = getRoundedCornerBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.unknown_face), 7);
						} catch (IOException e) {
							bitmap = getRoundedCornerBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.unknown_face), 7);
						}
						bmArray.add(bitmap);
					} else {
						cancel(true);
					}
				}
			} else if(this.method == "repoll") {
				if(params[0] == "poll") {
					try {
						sq.pollServer(new Task(0, null, params[1], null, 0, 0, null, 0, null, 0, 0, false));
						online = true;
						rmsg = 1;
					} catch (IOException e) {
						online = false;
						rmsg = 0;
					}
				} else if(params[0] == "query") {
					query(params[1].split(":")[0], Integer.parseInt(params[2]));
				} else if(params[0] == "both") {
					query(params[1].split(":")[0], Integer.parseInt(params[2]));
					try {
						sq.pollServer(new Task(0, null, params[1], null, 0, 0, null, 0, null, 0, 0, false));
						online = true;
					} catch (IOException e) {
						online = false;
					}
				}
			} else if (this.method == "timer") {
				for(int i = 0; i < repollfreq; i++) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					String waittime = "";
					int days = (int) Math.floor((repollfreq - i)/86400);
					int hrs = (int) Math.floor((repollfreq - i - (days*86400))/3600);
					int mins = (int) Math.floor((repollfreq - i - (hrs*3600))/60);
					int secs = (repollfreq - i - (mins*60) - (hrs*3600) - (days*86400));
					if(days > 0) waittime = waittime + days + "days ";
					if(hrs > 0) waittime = waittime + mins + "hrs ";
					if(mins > 0) waittime = waittime + mins + "min ";
					waittime = waittime + secs + "s";

					publishProgress("wait " + waittime);
				}
			}
			return "All Done!";
		}

		private void query(String host, int port) {
			try {
				Task g = new Task(name);
				g.setHost(host);
				g.setGs4Port(port);
				InetAddress ipAddr = sq.parseIp(g.getHost());
				DatagramSocket dp = sq.initConnection(ipAddr, g.getGs4Port());
				sq.queryServer(g, ipAddr, dp);
				rmsg = 4;
				online = true;
			} catch(UnknownHostException e) {
				online = false;
				rmsg = 2;
			} catch (IOException e) {
				online = false;
				rmsg = 3;
			}
		}
		
		@Override
		protected void onProgressUpdate(String... values) {
			((TextView) findViewById(R.id.repoll_btn)).setText(values[0]);
		}
		
		@Override
		protected void onPostExecute(String result) {
			super.onPostExecute(result);
			if(this.method == "loadFaces") {
				showDialog(0);
				progdialog.dismiss();
			} else if(this.method == "repoll") {
				hideSpinner();
				Toast.makeText(getBaseContext(), messages[rmsg], Toast.LENGTH_SHORT).show();
				times_online = times_online + (online ? 1 : 0);
				times_checked = times_checked + 1;
				((TextView) findViewById(R.id.repoll_btn)).setEnabled(true);
				csUpdateUI();
			} else if(this.method == "timer") {
				((TextView) findViewById(R.id.repoll_btn)).setEnabled(true);
			}
		}
		
		@Override
		protected void onCancelled() {
			cancelTask = false;
		}
		
		public Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
			Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
			Canvas canvas = new Canvas(output);

			final int color = 0xff424242;
			final Paint paint = new Paint();
			final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
			final RectF rectF = new RectF(rect);
			final float roundPx = pixels;

			paint.setAntiAlias(true);
			canvas.drawARGB(0, 0, 0, 0);
			paint.setColor(color);
			canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

			paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
			canvas.drawBitmap(bitmap, rect, rect, paint);

			return output;
		}
	}
}
